﻿using System;
using System.Collections.Concurrent;
using System.Threading;

namespace AudioSourceManager
{


    public class AudioVolumeMonitor
    {
        private int _sampleRate = 48000;
        private int _channels = 2;
        private int _bitsPerSample = 16;
        private int _timesPersecond = 25;
        private int _windowSizeMs => 1000 / _timesPersecond;
        private int BytesPerSample => _bitsPerSample / 8;
        private int BytesPerFrame => _channels * BytesPerSample;
        private int SamplesPerWindow => _sampleRate * _windowSizeMs / 1000;
        private int BytesPerWindow => SamplesPerWindow * BytesPerFrame;

        private readonly ConcurrentQueue<byte[]> _audioQueue = new ConcurrentQueue<byte[]>();

        private readonly Timer _volumeTimer;

        private UdpStreamReader _udpStream;

        private const float MaxAmplitude16Bit = 32768.0f; // 16位有符号整数的最大绝对值
        private const float MaxAmplitude32Bit = 2147483648.0f;// 32位有符号整数的最大绝对值

        public float VolumeLeft { get; private set; }
        public float VolumeRight { get; private set; }

        private int _tempVolumeLeft;
        private int _tempVolumeRight;

        public AudioVolumeMonitor(AudioPlayInfo audioPlayInfo, int timesPersecond)
        {
            _sampleRate = audioPlayInfo.SampleRate;
            _channels = audioPlayInfo.Channels;
            _bitsPerSample = audioPlayInfo.BitsPerSample;
            _timesPersecond = timesPersecond;
            _udpStream = new UdpStreamReader(audioPlayInfo.URL);
            _volumeTimer = new Timer(CalculateVolume, null, _windowSizeMs, _windowSizeMs);
            _udpStream.OnRecvMessage += i =>
            {
                ReceivePCMData(i);
            };

        }

        private void CalculateVolume(object state)
        {
            VolumeLeft = VolumeLeft * 0.7f + ProcessVolume(_tempVolumeLeft) * 0.3f;
            VolumeRight = VolumeRight * 0.7f + ProcessVolume(_tempVolumeRight) * 0.3f;
            _tempVolumeLeft = 0;
            _tempVolumeRight = 0;
        }

        public void Start()
        {
            _udpStream.Start();
        }

        public void Stop()
        {
            _udpStream.Stop();
            _volumeTimer.Dispose();
        }

        /// <summary>
        /// 计算音量
        /// </summary>
        /// <param name="state"></param>
        private void ReceivePCMData(byte[] packet)
        {
            for (int offset = 0; offset < packet.Length - 1; offset += BytesPerFrame)
            {
                int leftOri = BitConverter.ToInt16(packet, offset);
                int rightOri = BitConverter.ToInt16(packet, offset + 2);

                int absLeft = Math.Abs(leftOri);
                int absRight = Math.Abs(rightOri);

                if (absLeft > _tempVolumeLeft) _tempVolumeLeft = absLeft;
                if (absRight > _tempVolumeRight) _tempVolumeRight = absRight;
            }
        }

        private float ProcessVolume(int amplitude)
        {
            float MaxAmplitude = _bitsPerSample == 16 ? MaxAmplitude16Bit : MaxAmplitude32Bit;
            return amplitude / MaxAmplitude;
        }
    }
}
